package com.gl.saasservice.advertisement.service;

import com.gl.common.enums.OSSFileTypeEnum;
import com.gl.common.vo.ApiData;
import com.gl.framework.web.response.Result;
import com.gl.saasservice.advertisement.entity.SaasAd;
import com.gl.saasservice.advertisement.repository.SaasAdRepository;
import com.gl.saasservice.advertisement.vo.*;
import com.gl.saasservice.oss.config.OssConfig;
import com.gl.saasservice.oss.service.OSSService;
import net.sf.json.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 商品管理
 */
@Service
public class SaasAdService {

    private static final Logger LOG = LoggerFactory.getLogger(SaasAdService.class);

    private static final String SAAS_ADVERTISMENT = "saas:advertisement:%s";

    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private SaasAdRepository saasAdRepository;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private OSSService ossService;
    @Autowired
    private OssConfig ossConfig;


    /*
     *oss地址
     */
    @Value("${ali.oss.bucket}")
    private String bucket;


    public Result pages(Integer pageNumber, Integer pageSize, SaasAdVO filter, String sorts) {
        LOG.info("---ProductService.pages---> pageNumber={}, pageSize={}, filter={}, sorts={}", pageNumber, pageSize, filter, sorts);

        try {
            String columns = " SELECT \n" +
                    "a.id, \n" +
                    "a.space_id AS spaceId,\n" +
                    "s.name AS spaceName,\n" +
                    "a.name AS name,\n" +
                    "a.publish AS publish,\n" +
                    "a.expire AS expire,\n" +
                    "a.ad_pic AS adPic,\n" +
                    "a.ad_link AS adLink,\n" +
                    "a.status,\n" +
                    "a.auditor_status AS auditorStatus,\n" +
                    "a.auditor_id AS auditorId,\n" +
                    "a.creator_id AS creatorId,\n" +
                    "a.create_time AS createTime,\n" +
                    "a.content AS content\n" +
                    " FROM saas_ad a LEFT JOIN saas_ad_space s ON s.id = a.space_id\n ";

            String count = "SELECT COUNT(1) FROM saas_ad a LEFT JOIN saas_ad_space s ON s.id = a.space_id   ";
            StringBuffer where = new StringBuffer(" where  1 =1 ");
            String offsets = " LIMIT ? OFFSET ?";

            List<Object> args = new ArrayList<>();

            if (filter != null) {

                if (StringUtils.isNotBlank(filter.getSpaceName())) {
                    where.append(" AND s.name LIKE ? ");
                    args.add("%" + filter.getSpaceName() + "%");
                }
                if (StringUtils.isNotBlank(filter.getName())) {
                    where.append(" AND a.name LIKE ? ");
                    args.add("%" + filter.getName() + "%");
                }
                if (filter.getStatus() != null) {
                    where.append(" AND a.status =  ? ");
                    args.add(filter.getStatus());
                }
                if (filter.getAuditorStatus() != null) {
                    where.append(" AND a.auditor_status =  ? ");
                    args.add(filter.getAuditorStatus());
                }
            }

            ApiData<SaasAdVO> apiData = new ApiData<>();

            // 查询总记录数
            Long total = jdbcTemplate.queryForObject(count + where, Long.class, args.toArray());
            if (total == 0) {
                return Result.success(apiData);
            }
            // 查询分页数据
            where.append(" ORDER BY ").append(StringUtils.isNotEmpty(sorts) ? sorts : " a.create_time desc ").append("\n").append(offsets);

            args.add(pageSize);
            args.add(pageNumber * pageSize);
            List<SaasAdVO> data = jdbcTemplate.query(columns + where, new BeanPropertyRowMapper<>(SaasAdVO.class), args.toArray());

            apiData.setTotal(total);
            apiData.setData(data);
            return Result.success(apiData);
        } catch (Exception e) {
            LOG.error("SaasAdSpaceService pages Exception = {}", e.getMessage());
            return Result.fail();
        }
    }

    /**
     * 新增
     *
     * @return
     */
    public Result add(SaasAdVO vo, MultipartFile file) {

        try {
            if (file == null) {
                return Result.fail("广告图为空");
            }

            Result objectResultBean = ossService.putFile(bucket, file, OSSFileTypeEnum.AD.toString());
            String picUrl = String.valueOf(objectResultBean.getData());
            String adPic = ossService.getOssFilePath(picUrl);

            SaasAd entity = new SaasAd();
            // UserRealm.ShiroUser user = ShiroUserUtil.getUser();
            entity.setSpaceId(vo.getSpaceId());
            entity.setName(vo.getName());
            entity.setPublish(vo.getPublish());
            entity.setExpire(vo.getExpire());
            entity.setAdPic(adPic);
            entity.setAdLink(vo.getAdLink());
            entity.setStatus(0);
            entity.setAuditorStatus(0);
            entity.setCreateTime(new Date());
            entity.setContent(vo.getContent());
            saasAdRepository.save(entity);

            return Result.success(null);
        } catch (Exception e) {
            LOG.error("SaasAdService add Exception = {}", e.getMessage());
            return Result.fail();
        }
    }

    /**
     * 获取详情
     *
     * @param id
     * @return
     */
    public Result find(Long id) {


        Optional<SaasAd> optional = saasAdRepository.findById(id);
        if (!optional.isPresent()) {
            return Result.fail("id不存在");
        }
        SaasAd saasAd = optional.get();

        return Result.success(saasAd);

    }

    /**
     * 编辑
     *
     * @param vo
     * @return
     */
    public Result edit(SaasAdVO vo, MultipartFile file) {

        try {
            Optional<SaasAd> optional = saasAdRepository.findById(vo.getId());
            if (!optional.isPresent()) {
                return Result.fail("id不存在，无法编辑保存");
            }
            SaasAd entity = optional.get();
            entity.setSpaceId(vo.getSpaceId());
            entity.setName(vo.getName());
            entity.setAdLink(vo.getAdLink());

            if (file != null) {
                String fileKey = entity.getAdPic().replace(ossConfig.getBucketUrl(), "");
                ossService.deleteObject(bucket, fileKey);

                Result objectResultBean = ossService.putFile(bucket, file, OSSFileTypeEnum.AD.toString());
                String picUrl = String.valueOf(objectResultBean.getData());
                String adPic = ossService.getOssFilePath(picUrl);
                entity.setAdPic(adPic);
            }

            if (entity.getPublish() != null) {
                entity.setPublish(vo.getPublish());
            }
            if (entity.getExpire() != null) {
                entity.setExpire(vo.getExpire());
            }
            saasAdRepository.save(entity);

            return Result.success(null);
        } catch (Exception e) {
            LOG.error("SaasAdService edit Exception = {}", e.getMessage());
            return Result.fail();
        }
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    public Result delete(Long id) {

        try {
            Optional<SaasAd> saasAdSpace = saasAdRepository.findById(id);
            if (!saasAdSpace.isPresent()) {
                return Result.fail("id不存在无法删除");
            }
            saasAdRepository.deleteById(id);
            // 同步redis
            syncAdvSpaceToRedis();
            return Result.success(null);
        } catch (Exception e) {
            LOG.error("SaasAdService delete Exception = {}", e.getMessage());
            return Result.fail();
        }
    }


    /**
     * 审核方法
     *
     * @param vo
     * @return
     */
    public Result audit(AuditVO vo) {

        try {
            Map<Long, SaasAd> auditMap = new HashMap<>();
            // 获取选择中广告list集合
            Iterator<SaasAd> iterator = saasAdRepository.findAllById(vo.getIds()).iterator();
            // map结构  <广告id，广告对象>
            while (iterator.hasNext()) {
                SaasAd next = iterator.next();
                auditMap.put(next.getId(), next);
            }
            // 创建一个saasAdList 用于进行批量保存
            List<SaasAd> saasAdList = new ArrayList<>();
            // 不存在的广告
            List<String> failList = new ArrayList<>();
            // 遍历idList
            vo.getIds().stream().forEach(id -> {
                SaasAd saasAd = auditMap.get(id);
                if (saasAd == null) {
                    failList.add(id + "广告不存在，无法审核");
                }
                // 设置广告的审核状态
                saasAd.setAuditorStatus(vo.getAuditorStatus());
//                //符合符合审核通过而且上架的广告 都存放在redis
//                // redishashmap结构 广告位编码=[{广告图片、链接、名称}，{广告图片、链接、名称}]
//                if (saasAd.getStatus() == 1 && vo.getAuditorStatus()==1) {
//                    if (saasAd.getPublish() != null && saasAd.getExpire() != null) {
//                        if (new Date().before(saasAd.getExpire())) {
//                            stringRedisTemplate.opsForValue().set(String.format(SAAS_ADVERTISMENT, "c12346"), JSONUtils.toJSONString(saasAdList), 15, TimeUnit.MINUTES);
//                        }
//                    }
//                }
                saasAdList.add(saasAd);
            });

            if (failList.size() > 0) {
                return Result.fail(failList);
            }

            saasAdRepository.saveAll(saasAdList);

            // 同步redis
            syncAdvSpaceToRedis();

            return Result.success(null);
        } catch (Exception e) {
            LOG.error("SaasAdService audit Exception = {}", e.getMessage());
            return Result.fail();
        }
    }

    /**
     * 广告上下架状态
     *
     * @param vo
     * @return
     */
    public Result advertisingStatus(StatusVO vo) {

        try {
            Map<Long, SaasAd> statusMap = new HashMap<>();
            // 获取选择中广告list集合
            Iterator<SaasAd> iterator = saasAdRepository.findAllById(vo.getIds()).iterator();
            // map结构  <广告id，广告对象>
            while (iterator.hasNext()) {
                SaasAd next = iterator.next();
                statusMap.put(next.getId(), next);
            }
            // 创建一个saasAdList 用于进行批量保存
            List<SaasAd> saasAdList = new ArrayList<>();
            // 失败的广告
            List<String> failList = new ArrayList<>();
            // 遍历idList
            vo.getIds().stream().forEach(id -> {
                SaasAd saasAd = statusMap.get(id);
                if (saasAd == null) {
                    failList.add(id + "广告不存在无法操作");
                }
                // 设置广告的审核状态
                saasAd.setStatus(vo.getStatus());
                saasAdList.add(saasAd);
            });

            if (failList.size() > 0) {
                return Result.fail(failList);
            }

            saasAdRepository.saveAll(saasAdList);

            // 同步redis
            syncAdvSpaceToRedis();

            return Result.success(null);
        } catch (Exception e) {
            LOG.error("SaasAdService audit Exception = {}", e.getMessage());
            return Result.fail();
        }
    }

    /**
     * 选中删除
     *
     * @param vo
     * @return
     */
    public Result selectDelete(DeleteVO vo) {

        try {
            Map<Long, SaasAd> statusMap = new HashMap<>();
            // 获取选择中广告list集合
            Iterator<SaasAd> iterator = saasAdRepository.findAllById(vo.getIds()).iterator();
            // map结构  <广告id，广告对象>
            while (iterator.hasNext()) {
                SaasAd next = iterator.next();
                statusMap.put(next.getId(), next);
            }
            List<SaasAd> saasAdList = new ArrayList<>();
            // 失败广告
            List<String> failList = new ArrayList<>();
            vo.getIds().stream().forEach(id -> {
                SaasAd saasAd = statusMap.get(id);
                if (saasAd == null) {
                    failList.add(id + "广告不存在,无法操作");
                }
                saasAdList.add(saasAd);
            });

            if (failList.size() > 0) {
                return Result.fail(failList);
            }

            saasAdRepository.deleteAll(saasAdList);

            // 同步redis
            syncAdvSpaceToRedis();

            return Result.success(null);
        } catch (Exception e) {
            LOG.error("SaasAdService selectDelete Exception = {}", e.getMessage());
            return Result.fail();
        }
    }


    /**
     * 同步redis方法
     */
    public void syncAdvSpaceToRedis() {
        try {

            // 先删除redis中的数据
            String sql1 = "SELECT code FROM saas_ad_space";
            List<AdvTaskVO> adSpaceVos = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(AdvTaskVO.class));
            adSpaceVos.forEach((code) -> {
                stringRedisTemplate.delete(String.format(SAAS_ADVERTISMENT, code.getCode()));
            });

            String sql = "SELECT\n" +
                    "  s.code,\n" +
                    "  a.ad_pic,\n" +
                    "  a.ad_link,\n" +
                    "  a.name,\n" +
                    "  a.content\n" +
                    "FROM\n" +
                    "  saas_ad a\n" +
                    "  LEFT JOIN saas_ad_space s\n" +
                    "    ON s.id = a.space_id\n" +
                    "WHERE a.`auditor_status` = 1\n" +
                    "  AND a.`status` = 1\n" +
                    "  AND a.`expire`>=NOW()";

            List<AdvTaskVO> advTaskVos = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(AdvTaskVO.class));
            Map<String, List<AdvTaskVO>> collect = advTaskVos.stream().collect(Collectors.groupingBy(AdvTaskVO::getCode));
            Set<String> set = collect.keySet();
            collect.forEach((code, vos) -> {
                JSONArray jsonObject = JSONArray.fromObject(vos.toArray());
                stringRedisTemplate.opsForValue().set(String.format(SAAS_ADVERTISMENT, code), jsonObject.toString(), 43200, TimeUnit.MINUTES);
            });

//            for (String code:set) {
//                List<AdvTaskVO> list = collect.get(code);
//                for (int i = 0; i < list.size(); i++) {
//
//
//                }
//                stringRedisTemplate.opsForValue().set(String.format(SAAS_ADVERTISMENT,code),
//                        JSONUtils.toJSONString("123"),15, TimeUnit.MINUTES);
//            }


        } catch (Exception e) {
            LOG.error("AdvertisementScheduledTasks AdvertisementTask Exception = {}", e.getMessage());
        }

    }
}
